package com.shopping_assistant.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import android.location.Location;

import com.google.android.maps.GeoPoint;

public class ShopController {

	public static final double LATITUDE_PER_KM = 64.0;
	public static final double LONGTITUDE_PER_KM = 111.0;
	
	private List<Shop> shops;
	
	private static ShopController instance;
	
	public static ShopController getInstance() {
		
		if(instance == null)
			instance = new ShopController();
		
		return instance;
	}
	
	private ShopController() {
		shops = new ArrayList<Shop>();
	}
	
	public List<Shop> getShops() {
		return shops;
	}
	
	public List<Offer> getAllOffers() {
		List<Offer> allOffers = new ArrayList<Offer>();
		
		for(Shop shop : shops) {
			for(Offer offer : shop.getCurrentOffers()) {
				allOffers.add(offer);
			}
		}
		
		Collections.sort(allOffers, Offer.compareByViews());
		return allOffers;
	}
	
	public List<Shop> getShopsInRange(Location x, Location y) {
		return null;
	}
	
	public List<Offer> getAllOffersFromShop(Shop shop) {
		for(Shop object : shops) {
			if(object.getName().equals(shop.getName())) {
				return object.getCurrentOffers();
			}
		}
		return null;
	}
	
	public List<Shop> findShopsFromSmallestSquare(GeoPoint myLocation) {

		List<Shop> list = null;

		if (!shops.isEmpty()) {

			// No need to run algorithm if only one shop
			if(shops.size() == 1)
				return shops;
			
			// Find AED from a square of 1 km and then 1*2 km, 2*2 km, 4*2km and
			// so on...

			double leftX = 0.0;
			double rightX = 0.0;
			double bottomY = 0.0;
			double topY = 0.0;

			int mulitiplier = 1;
			double lastResultx = LATITUDE_PER_KM * mulitiplier;
			double lastResulty = LONGTITUDE_PER_KM * mulitiplier;

			while (list == null || list.size() == 0) {

				lastResultx = lastResultx * mulitiplier;
				lastResulty = lastResulty * mulitiplier;

				leftX = (myLocation.getLatitudeE6() / 1E6) - lastResultx;
				rightX = (myLocation.getLatitudeE6() / 1E6) + lastResultx;
				bottomY = (myLocation.getLongitudeE6() / 1E6) - lastResulty;
				topY = (myLocation.getLongitudeE6() / 1E6) + lastResulty;

				list = selectOnPosition(leftX, rightX, bottomY, topY);
			}
		}

		return list;
	}
	
	public Shop findShopByLocation(double latitude, double longitude) {
		for(Shop shop : shops) {
			if(shop.getLatitude() == latitude && shop.getLongitude() == longitude ) {
				return shop;
			}
		}
		return null;
	}
	
	public Offer findOfferByID(int offerID) {
		for(Shop shop : shops) {
			List<Offer> shopOffers = shop.getCurrentOffers();
			for(Offer offer : shopOffers) {
				if(offer.getOfferId() == offerID) {
					return offer;
				}
			}
		}
		return null;
	}
	
	private List<Shop> selectOnPosition(double leftX, double rightX,
			double bottomY, double topY) {

		List<Shop> result = new ArrayList<Shop>();

		for (Shop shop : shops) {

			if (shop.getLatitude() >= leftX
				&& shop.getLatitude() <= rightX
				&& shop.getLongitude() >= bottomY
				&& shop.getLongitude() <= topY)
				
				result.add(shop);
		}

		return result;
	}

	public Shop findClosestShop(Location lastLocation) {
		Shop shop = null;
		double distance = -1;
		double minDistance = Double.MAX_VALUE;
		Shop foundShop = null;
		
		for(int i = 0; i < shops.size(); i++) {
			shop = shops.get(i);
			
			distance = shop.distanceTo(lastLocation);
			
			if(distance < minDistance) {
				minDistance = distance;
				foundShop = shop;
			}
		}
		
		return foundShop;
	}
	
}
